Создание нативных образов с Spring Native и Axiom NIK

В семье Spring пополнение!


Spring ー легендарное семейство Java-фреймворка, гордостью которого является Spring Boot. Spring в этом году празднует 18 лет со дня основания и продолжает расти и крепнуть. Хотя новые фреймворки появляются постоянно, Spring остается главным. Легковесный, безопасный, кастомизируемый и гибкий инструмент программирования стал эталоном современной разработки на Java.

Однако не так давно в семье Spring случилось пополнение ー Spring Native. Хотя он все еще находится в бета-версии, он успел привлечь внимание разработчиков со всего мира. Его уже можно протестировать.

Наша технология Axiom Native Image Kit (NIK) полностью совместима с Spring Boot даже в бета-версии. Познакомьтесь с ней ниже или обратитесь к нашим инженерам за консультацией.

В чем особенность Spring Native?

Spring Native ー это версия фреймворка Spring со встроенной поддержкой компиляции приложений в нативные образы с помощью компилятора Graal. Он позволяет запускать приложения Spring в любой системе без необходимости установки JRE, так как Java Virtual Machine встроена в исполняемый файл приложения, и обеспечивает почти мгновенный запуск, быстрое достижение пиковой производительности и минимальное потребление ресурсов. Посредством статического (ahead-of-time, AOT) компилятора Spring Native создает небольшой образ, содержащий слой ОС, зависимости для запуска кода и компоненты OpenJDK и Spring. Все это упаковано в один исполняемый файл.

В результате сборка выполняется дольше и иногда возможностей оптимизации рантайма меньше, но взамен вы получаете ускоренный запуск и маленький контейнер с упрощенной структурой. Это идеально подходит для ситуаций, когда необходимо выполнить большое количество “чистых” развертываний, использовать минимальный объем памяти или часто перезапускать сервисы.

Spring становится круче!

Благодаря новому члену семьи Spring укрепил свои позиции:

  • Spring сравнял счет с конкурентами, устранив главное препятствие на своем пути. Теперь у Spring есть поддержка нативного образа GraalVM, как и у Quarkus и Micronaut.
  • В «‎облачную» эпоху размер микросервисов важен как никогда. Каждый мегабайт стоит времени и денег. Как правило, приложения Spring со временем разбухают, но Spring Native решил эту проблему.
  • Хотя Spring Native пока находится в экспериментальной фазе, вы можете сгенерировать и скачать каркас приложения, которое использует spring native для сборки контейнера, с официального сайта разработчика и немного поиграть с ним. Создайте с его помощью образы и убедитесь, что по сравнению со стандартными jar-файлами Spring запуск быстрее, а объем потребляемой памяти меньше.
  • Хотя технология была разработана менее, чем за два года, потребовалось немало усилий со стороны разработчиков, чтобы сгладить различия в поведении Spring Boot и GraalVM. AOT-компиляция в сочетании с динамичным, модульным поведением рантайма Spring ー не самый гармоничный союз. Но и эту проблему удалось устранить с помощью статической генерации служебного кода (входит в spring-aot плагин для maven или gradle). Это значительный шаг вперед и теперь вы можете воспользоваться преимуществами обеих технологий.

Давайте познакомим Spring Native и Axiom NIK!

Как мы уже говорили, Spring Native уже можно протестировать. Хотя Spring на базе JDK 17 будет содержать еще много новых улучшений, предлагаю пока поэкспериментировать.

Итак, преобразуем jar в нативный образ. В качестве примера используем проект petclinic, в качестве рантайма ー Liberica JDK (с 2022 года - Axiom JDK) 11, а инструментом будет Axiom NIK.

Самый простой способ начать работу с Spring Native ー создать артефакт с помощью Spring Initializr или скачать готовые примеры с https://github.com/spring-projects-experimental/spring-native/tree/main/samples. Мы используем приложение petclinic-jdbc.

Изучите содержимое файла pom.xml проекта Maven. В разделах main и parent вы увидите следующее:

  • зависимости включают spring-native plugin (текущая версия: org.springframework.experimental:spring-native:0.10.3-SNAPSHOT);
  • раздел сборки включает spring-aot-maven-plugin и org.graalvm.buildtools:native-maven-plugin;
  • имеется отдельный нативный профиль с собственной конфигурацией native-maven-plugin;
  • org.springframework.boot:spring-boot-maven-plugin сконфигурирован таким образом, чтобы можно было использовать компоновщик paketo buildpacks (paketobuildpacks/builder:tiny), который по умолчанию находится в режиме BP_NATIVE_IMAGE=true.

Есть несколько вариантов сборки и запуска приложения. Но в любом случае, нам понадобится JDK для запуска Maven. У меня установлена Liberica JDK для Linux, поэтому JAVA_HOME настраивается через командную строку соответствующим образом.

Классический JAR-файл

Начнем с создания JAR-файла.

JAVA_HOME=/usr/lib/jvm/bellsoft-java11-amd64/ ~/apache-maven-3.8.2/bin/mvn install

В результате вы получите target/petclinic-jdbc-0.0.1-SNAPSHOT.jar размером 24 МБ. Можете запустить его стандартным способом:

java -jar target/petclinic-jdbc-0.0.1-SNAPSHOT.jar

Время запуска ー примерно 2,4 секунды.

Дефолтный контейнер с нативным образом

Соберем контейнер.

Если у вас Windows или macOS, необходимо зарезервировать как минимум 8 ГБ оперативной памяти для запуска контейнеров в Docker Desktop.

Для создания контейнера средствами maven-плагина, введите следующую команду:

JAVA_HOME=/usr/lib/jvm/bellsoft-java11-amd64/ ~/apache-maven-3.8.2/bin/mvn spring-boot:build-image

Мы получили контейнеризированный образ, который можно запустить командой

docker run -it docker.io/library/petclinic-jdbc:0.0.1-SNAPSHOT

Поскольку это нативный образ, время запуска составляет всего 0,1 секунды. Разница с 2,4 секунды колоссальная (в десятки раз)!

Чтобы облегчить работу, скачаем полностью функциональное приложение с выбранной базой данных, используя конфигурацию docker-compose и docker-compose.yml:

docker-compose up

С помощью этого метода можно также получить стандартную сборку многослойного контейнеризированного образа. Для этого измените BP_NATIVE_IMAGE на false (JVM и .jar внутри).

Нативный образ

В предыдущем разделе мы упомянули paketo buildpack. Он базируется на конкретной версии GraalVM и native-image. Текущая версия: GraalVM 21.2.0 (версия Java 11.0.12). Но можно использовать нативный профиль, о котором мы говорили ранее, и создавать нативные образы любым способом. Давайте используем Axiom NIK на основе GraalVM 21.2.0 и Liberica JDK 11.0.12.

Сначала скачайте Axiom NIK Core. Версия Core наилучшим образом подходит для нативных образов Java, так как содержит Axiom VM и нативный образ (на базе GraalVM) без дополнительных языков. Выберите платформу и тип инсталляции. В моем случае, это Linux x86_64 и .tar.gz, Axiom NIK версии 21.2.0.

Теперь укажите полный путь установки JAVA_HOME и вызовите нативный профиль для сборки:

JAVA_HOME=$(pwd)/bellsoft-axiom-vm-core-openjdk11-21.2.0 ~/apache-maven-3.8.2/bin/mvn -Pnative install

Процесс занимает примерно 10 минут (при этом используются 8 ядер CPU и 8 ГБ RAM). В результате мы получим бинарный файл target/petclinic-jdbc размером 118 МБ. Запустите его. Файл запустится всего за десятую долю секунды, лучший показатель на сегодня! В этот раз мы использовали последнюю версию инструмента для создания нативных образов, а не версию по умолчанию. Но иногда нет возможности обновить версию релиза, пока не будут решены все проблемы, связанные с миграцией, поэтому можно сделать наоборот.

Axiom любит Spring

Как видите, Spring и Axiom NIK хорошо смотрятся вместе даже в экспериментальной фазе.

Однако если вы пока не готовы перейти на Java 17, вы всегда можете воспользоваться предыдущими LTS-версиями Axiom NIK. В нашей статье, предваряющей выход 17 версии, мы описали все новые и удаленные функции новой версии OpenJDK. Если вас волнует обратная совместимость, можете продолжать работать с Liberica JDK 11; эта версия будет получать обновления до 2027 года С более подробной информацией можете ознакомиться на странице дорожной карты поддержки.

Сейчас совместная работа Spring Boot и GraalVM требует значительной кастомизации. Но в сентябре вышла Java 17, чуть позже выйдет новая версия Spring Boot. В итоге создавать нативные образы будет гораздо удобнее. А пока предлагаем окунуться в мир Spring Boot, протестировать его и убедиться, что ваши Spring-приложения еще никогда не запускались так быстро!

Author image

Олег Чирухин

Директор по коммуникациям с разработчиками (DevRel)

Команда Axiom JDK roman.karpov@axiomjdk.ru Команда Axiom JDK logo Axiom Committed to Freedom 199 Obvodnogo Kanala Emb. 190020 St. Petersburg RU +7 812-336-35-67 Команда Axiom JDK 199 Obvodnogo Kanala Emb. 190020 St. Petersburg RU +7 812-336-35-67